#include "Aquarium_Modes.h";

#include "Aquarium_Devices.h";
#include "Auto_Top.h";

extern Aquarium_Devices aquarium_devices;
extern Auto_Top                       auto_top;
extern Clock                               clock;

extern LiquidCrystal lcd;

prog_char mode_name_0[] PROGMEM = "Normal";
prog_char mode_name_1[] PROGMEM = "Feeding Fish";
prog_char mode_name_2[] PROGMEM = "Feeding 1";
prog_char mode_name_3[] PROGMEM = "Feeding 2";
prog_char mode_name_4[] PROGMEM = "Water Change";
prog_char mode_name_5[] PROGMEM = "Mode 6";
prog_char mode_name_6[] PROGMEM = "Mode 7";
prog_char mode_name_7[] PROGMEM = "Elc Blackout";

PROGMEM const char *modes_name_table[] = 
{   
  mode_name_0,
  mode_name_1,
  mode_name_2,
  mode_name_3,
  mode_name_4,
  mode_name_5,
  mode_name_6,
  mode_name_7
};



Aquarium_Modes::Aquarium_Modes()  : 
Curr_Aquarium_mode(0) ,
Timer(0),
mode_change(0){
  init();
};

void Aquarium_Modes::init(){

  for (int i = 0 ; i  < NUMBER_OF_MODES ; ++i){
    int address = EEPROM_MODES_ADDRESS_START + (EEPROM_MODES_ADDRESS_OFFSET *i);
    MoveTo[i] = EEPROM.read(address++);
    MoveToAfter[i] = EEPROM.read(address++);
    for (int j = 0 ; j  < MODES_NUMBER_OF_TIMERS ; ++j){   
      Timer_On[ i ] [ j ] = EEPROM.read(address++);
      Timer_HR[ i ][ j ] = EEPROM.read(address++);
      Timer_MIN[ i ][ j] = EEPROM.read(address++);
      Timer_DAY[ i ][ j] = EEPROM.read(address++);
      Timer_MoveTo[ i ][ j ] = EEPROM.read(address++);
    }
  }

}

void Aquarium_Modes::Save_To_EEPROM(){
  for (int i = 0 ; i  < NUMBER_OF_MODES ; ++i){
    int address = EEPROM_MODES_ADDRESS_START + (EEPROM_MODES_ADDRESS_OFFSET *i);
    EEPROM.write(address++, MoveTo[i]) ;
    EEPROM.write(address++, MoveToAfter[i]) ;
    for (int j = 0 ; j  < MODES_NUMBER_OF_TIMERS ; ++j){   
      EEPROM.write(address++, Timer_On[ i ] [ j ] );
      EEPROM.write(address++, Timer_HR[ i ][ j ] );
      EEPROM.write(address++, Timer_MIN[ i ][ j] );
      EEPROM.write(address++, Timer_DAY[ i ][ j] );
      EEPROM.write(address++, Timer_MoveTo[ i ][ j ] );
    }
  }
}

void Aquarium_Modes::MoveToMode( byte ModeNum ){
  Curr_Aquarium_mode = ModeNum;
  Timer = MoveToAfter[ModeNum];
  mode_change = true;
  auto_top.update(0);
  delay(250);
  aquarium_devices.update_devices();
  delay(250);
   lcd.begin(LCD_COLUMNS, LCD_LINES);
}

void Aquarium_Modes::update(){
  byte Cur_Hr = clock.get_hr();
  byte Cur_Min = clock.get_min();
   byte Cur_Day = clock.get_day();

  if ( Timer > 1){
    --Timer;
  }
  else if ( Timer == 1){
    MoveToMode(MoveTo[Curr_Aquarium_mode]);
  }

  for (int i = 0 ; i  < MODES_NUMBER_OF_TIMERS ; ++i){   
    if (    Timer_On[ Curr_Aquarium_mode ] [ i ] &&
      (Timer_HR[ Curr_Aquarium_mode ][ i ] ==  Cur_Hr) &&
      (Timer_MIN[ Curr_Aquarium_mode ][ i] == Cur_Min)  &&
      (bitRead(Timer_DAY[ Curr_Aquarium_mode ][ i] , Cur_Day ) )    ){
      MoveToMode(Timer_MoveTo[ Curr_Aquarium_mode ][ i ]);
    }
  }

}



void Aquarium_Modes::SetMoveTo(byte ModeNum, byte Mode){ 
  MoveTo[ModeNum] = Mode;
}
byte Aquarium_Modes::GetMoveTo(byte ModeNum){ 
  return MoveTo[ModeNum];
}
void Aquarium_Modes::SetMoveToAfter(byte ModeNum, byte Time){ 
  MoveToAfter[ModeNum] =Time;
}
byte Aquarium_Modes::GetMoveToAfter(byte ModeNum){ 
  return MoveToAfter[ModeNum];
}

void Aquarium_Modes::SetTimer_On(byte ModeNum, byte Timer ,bool On){ 
  Timer_On[ModeNum] [ Timer ] = On;
}
bool Aquarium_Modes::GetTimer_On(byte ModeNum, byte Timer){ 
  return Timer_On[ModeNum][Timer];
}

void Aquarium_Modes::SetTimer_HR(byte ModeNum, byte Timer ,byte HR ){ 
  Timer_HR[ModeNum] [ Timer ] = HR;
}
byte Aquarium_Modes::GetTimer_HR(byte ModeNum, byte Timer){ 
  return Timer_HR[ModeNum][Timer];
}


void Aquarium_Modes::SetTimer_MIN(byte ModeNum, byte Timer ,byte Min){ 
  Timer_MIN[ModeNum] [ Timer ] = Min;
}
byte Aquarium_Modes::GetTimer_MIN(byte ModeNum, byte Timer){ 
  return Timer_MIN[ModeNum][Timer];
}



void Aquarium_Modes::SetTimer_DAY(byte ModeNum, byte Timer ,byte Day){ 
  Timer_DAY[ModeNum] [ Timer ] = Day;
}
byte Aquarium_Modes::GetTimer_DAY(byte ModeNum, byte Timer){ 
  return Timer_DAY[ModeNum][Timer];
}


void Aquarium_Modes::SetTimer_MoveTo(byte ModeNum, byte Timer ,byte MoveTo){ 
  Timer_MoveTo[ModeNum] [ Timer ] = MoveTo;
}
byte Aquarium_Modes::GetTimer_MoveTo(byte ModeNum, byte Timer){ 
  return Timer_MoveTo[ModeNum][Timer];
}





void  Aquarium_Modes::Print(byte Mode_num){
  strcpy_P(buffer, (char*)pgm_read_word(&(  modes_name_table[ Mode_num ]     )));
  lcd.print(buffer );
}

void  Aquarium_Modes::Print(){

  strcpy_P(buffer, (char*)pgm_read_word(&(  modes_name_table[ Curr_Aquarium_mode]     )));
  lcd.print(buffer );
}












